package zcatt.ex001.osgi.client;

//import org.eclipse.core.runtime.ServiceCaller;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

import zcatt.ex001.osgi.service.AnnotationService;
import zcatt.ex001.osgi.service.BasicService;
import zcatt.ex001.osgi.service.DeclarativeService;

public class Activator implements BundleActivator {

	private static BundleContext context;

	static BundleContext getContext() {
		return context;
	}

	public void start(BundleContext bundleContext) throws Exception {
		Activator.context = bundleContext;
		
		System.out.println(getClass().getName() + " start....");
		
		
		//#.使用basic service
		System.out.println("\nPART 1. use basicService");
		
		ServiceReference<BasicService> basicServRef = bundleContext.getServiceReference(BasicService.class);
		
		BasicService basicServ = bundleContext.getService(basicServRef);
		basicServ.doService();
		
		bundleContext.ungetService(basicServRef);

		
		//#.使用declarative service
		System.out.println("\nPART 2. use declarativeService");
		
		ServiceReference<DeclarativeService> declServRef = bundleContext.getServiceReference(DeclarativeService.class);
		
		DeclarativeService declServ = bundleContext.getService(declServRef);
		declServ.doService();
		
		bundleContext.ungetService(declServRef);
		
		//使用annotation service
		System.out.println("\nPART 3. use annotationService");
		
		ServiceReference<AnnotationService> annServRef = bundleContext.getServiceReference(AnnotationService.class);
		
		AnnotationService annServ = bundleContext.getService(annServRef);
		annServ.doService();
		
		bundleContext.ungetService(annServRef);
		
		//使用ServiceTracker
		//ServiceTracker有3种构造方式,
		System.out.println("\nPART 4. use serviceTracker");
		
		ServiceTracker<BasicService, BasicService> servTrackerNoCustomizer;
		ServiceTracker<BasicService, String> servTracker;
		
		//构造1. ServiceTracker(final BundleContext context, final ServiceReference<S> reference, final ServiceTrackerCustomizer<S, T> customizer)

		//basicServRef = bundleContext.getServiceReference(BasicService.class);
		
		//构造1之无ServiceTrackerCustomizer
		System.out.println("\nServiceTracker constructor 1 with  ServiceCustomizer null");
		servTrackerNoCustomizer = new ServiceTracker<>(bundleContext, basicServRef, null);
		servTrackerNoCustomizer.open();
		servTrackerNoCustomizer.getService().doService();
		servTrackerNoCustomizer.close();
		
		//构造1之有ServiceTrackerCustomizer
		System.out.println("\nServiceTracker constructor 1 with  ServiceCustomizer");
		servTracker = new ServiceTracker<>(bundleContext, basicServRef, new BasicServiceCustomizer("trackedObj_1"));
		servTracker.open();
		
		String trackedObjName = servTracker.getService();
		System.out.println(trackedObjName + " is used");
		ServiceReference<BasicService> sr = servTracker.getServiceReference();
		
		BasicService servObj = bundleContext.getService(basicServRef);
		servObj.doService();		
		bundleContext.ungetService(basicServRef);
		

		servTracker.close();
		
				
		//构造2. ServiceTracker(final BundleContext context, final String clazz, final ServiceTrackerCustomizer<S, T> customizer)
		System.out.println("\nServiceTracker constructor 2 with  ServiceCustomizer null");
		servTracker = new ServiceTracker<>(bundleContext, BasicService.class.getName(), new BasicServiceCustomizer("trackedObj_2"));
		servTracker.open();
		
		trackedObjName = servTracker.getService();
		System.out.println(trackedObjName + " is used");
		sr = servTracker.getServiceReference();
		
		servObj = bundleContext.getService(basicServRef);
		servObj.doService();		
		bundleContext.ungetService(basicServRef);		

		servTracker.close();
		
		//构造3. ServiceTracker(final BundleContext context, final Filter filter, final ServiceTrackerCustomizer<S, T> customizer)
		System.out.println("\nServiceTracker constructor 3 with  ServiceCustomizer null");
		Filter filter = bundleContext.createFilter( "(" + Constants.OBJECTCLASS + "=" + BasicService.class.getName() + ")");
		servTracker = new ServiceTracker<>(bundleContext, filter, new BasicServiceCustomizer("trackedObj_3"));
		servTracker.open();
		
		trackedObjName = servTracker.getService();
		System.out.println(trackedObjName + " is used");
		sr = servTracker.getServiceReference();
		
		servObj = bundleContext.getService(basicServRef);
		servObj.doService();		
		bundleContext.ungetService(basicServRef);		

		servTracker.close();

		//构造4. ServiceTracker(final BundleContext context, final Class<S> clazz, final ServiceTrackerCustomizer<S, T> customizer)
		System.out.println("\nServiceTracker constructor 4 with  ServiceCustomizer null");
		servTracker = new ServiceTracker<>(bundleContext, BasicService.class, new BasicServiceCustomizer("trackedObj_3"));
		servTracker.open();
		
		trackedObjName = servTracker.getService();
		System.out.println(trackedObjName + " is used");
		sr = servTracker.getServiceReference();
		
		servObj = bundleContext.getService(basicServRef);
		servObj.doService();		
		bundleContext.ungetService(basicServRef);		

		servTracker.close();

/*需要较多的dependency bundle, 暂注掉		
		//使用serviceCaller
		System.out.println("\nPART 5. use serviceCaller");
		ServiceCaller.callOnce(getClass(), BasicService.class, serv->{ serv.doService(); });
*/		
		
	}

	public void stop(BundleContext bundleContext) throws Exception {
		Activator.context = null;

		System.out.println(getClass().getName() + " stop....");
	}

	public class BasicServiceCustomizer implements ServiceTrackerCustomizer<BasicService, String> {
		String name;
		
		public BasicServiceCustomizer(String name)
		{
			this.name = name;
		}
		
		@Override
		public String addingService(ServiceReference<BasicService> reference) {
			System.out.println(getClass().getName() + " addingService....");
			return name;
		}

		@Override
		public void modifiedService(ServiceReference<BasicService> reference, String service) {
			System.out.println(getClass().getName() + " modifiedService...." + service);
		}

		@Override
		public void removedService(ServiceReference<BasicService> reference, String service) {
			System.out.println(getClass().getName() + " removedService...." + service);		
		}
		
	}
}
